@rem -*- Perl -*-
@setlocal

@if (%PERL_BIN_PATH%) == () ( 
    @perl -x "%~dpnx0" %* 
    @goto :eof
) else (
    @if "%PERL_BIN_PATH%" == "UNDEFINED" (
        @perl -x "%~dpnx0" %* 
        @goto :eof
    ) else (
        @%PERL_BIN_PATH%\perl -x "%~dpnx0" %* 
        @goto :eof
    )
)
@goto :eof
#!perl

##########################################################
## Run EspFe + ctobpl 
##########################################################
    
## Environment variables
    my $HAVOC_DLL_DIR;
my $clean = 0;
my $useHoudini = 0;
my $oacr = 0;

sub MyExec{
    my $cmd = shift;
    print "$cmd \n";
    system("$cmd");
}


# Infer HAVOC_DLL_DIR
sub InferHavocDllDir{
    if (-d $ENV{'HAVOC_DLL_DIR'}) {
	print ("Picking up HAVOC executables from $ENV{'HAVOC_DLL_DIR'}...\n");
    } elsif (-d $ENV{'ESP_ROOT'}) {
	my $esproot = $ENV{"ESP_ROOT"};    
	$ENV{'HAVOC_DLL_DIR'} = "$esproot\\..\\binaries.x86chk";
	print ("(ESP_ROOT set) Picking up HAVOC executables from $ENV{'HAVOC_DLL_DIR'}...\n");
    } else {
	die "Define HAVOC_DLL_DIR or ESP_ROOT...\n";
    }
}

# Infer directory for havoc.config
sub InferHavocFeConfig{
    if (-e $ENV{'HAVOCFECONFIG'}){
	print "Using $ENV{'HAVOCFECONFIG'} as havoc.config...\n";
    } elsif(-e "havoc.config") { # in the same directory
	$ENV{'HAVOCFECONFIG'} = "havoc.config";
	print "Using HAVOCFECONFIG=havoc.config...\n";
    } else {
	die "Define HAVOCFECONFIG or put havoc.config in the same directory...\n";
    }
}


sub Clean {
    my $cmd = "del *.ann *.cfgf *.cgf *.vfgf *.vmapf bench.all *.cg *.lib "
    . "*.scc *.info *.blob count *.html *.files ScreenDump "
    . "*.cfg *.cfg.txt *.xml *.pfxmsg *.vfg *.obj *.out *~ *.scg "
    . "errors.xml.lst run.log.lst *.dotty *.count > NUL 2>&1";
    system($cmd);

}

sub RunEspFeNmake {
    print ("--------------------------\n");
    print ("Executing nmake + EspFe...\n");
    print ("--------------------------\n");

    MyExec("nmake PLUGIN=EspFe -nologo > espfe.dmp");

}

sub RunEspFeOacr {
    print ("--------------------------\n");
    print ("Executing oacr + EspFe...\n");
    print ("--------------------------\n");

    #copy EspFe dll to OACR plugins directory
    MyExec("copy %HAVOC_DLL_DIR%\\EspFe.dll %_NTDRIVE%%_NTROOT%\\tools\\analysis\\x86\\oacr\\prefast\\x86\\bin\\plugins\\");

    #write the oacruser.ini to use EspFe
    print "Writing oacruser.ini...\n";
    open (OACRINI, ">$ENV{'_NTDRIVE'}$ENV{'_NTROOT'}\\developer\\$ENV{'USERNAME'}\\oacruser.ini");
    print OACRINI "[defaults]\n";
    print OACRINI "PrefastModules = EspFe\n";
    print OACRINI "WarningLocations = <all>\n";
    close OACRINI;

    MyExec("oacr clean all");
    MyExec("oacr set all");
    MyExec("build -cLZ");
    MyExec("oacr check all");

}


sub RunEspFe {
    if ($useHoudini eq 1){
	$ENV{'CL'} = "/D USE_HOUDINI=1"; # for houdini options 
    }
    
    if ($oacr eq 1){
	RunEspFeOacr();
    } else {
	RunEspFeNmake();
    }

    MyExec("dir /b/s *.rawcfgf > system.cfg.files");

}

sub GenerateBlob{
    print ("-----------------------\n");
    print ("Generating blob file...\n");
    print ("-----------------------\n");

    MyExec("%HAVOC_DLL_DIR%\\cfglink /DoVMap=false /DoSCFGMerging=true /RemoveLinkage=true /CFGFiles=\@system.cfg.files");
}

# try to infer if ctobpl args have TranslateMode={Houdini,InferHoudini}
sub InferUseHoudini{
    my @arglist = shift;
    while($arglist[0]) {
	my $opt = shift @arglist;
	if ($opt =~ /^\-TranslateMode=Houdini$/){
	    $useHoudini = 1;
	} elsif ($opt =~ /^\-TranslateMode=InferHoudini$/){
	    $useHoudini = 1;
	} elsif ($opt =~ /^\-TranslateMode=InferHoudiniHavocFe$/){
	    $useHoudini = 1;
	}  else {
	}
    }
}


sub RunTranslator {
    my $cmd;
    my $time0 = time;
    print ("--------------------------\n");
    print ("Executing ctobpl module...\n");
    print ("--------------------------\n");
    my $cmd = "%HAVOC_DLL_DIR%\\ctobpl  /SETTINGS=%HAVOCFECONFIG% /BreakAtAssert=1 /RunDirectory=. @ARGV";
    MyExec($cmd);
}

sub ProcessOptions {
    if ($ARGV[0]){
	if (@ARGV[0] eq "/help" || @ARGV[0] eq "-help"){
	    print "usage: havoc [/help|/oacr] [<string input to ctobpl.exe>]\n"; 
	    print "\t  /help: prints this message\n";
	    print "\t  /oacr: use OACR to compile\n";
	    print "\t  the remaining is passed on to ctobpl.exe\n";
	    die "\n";
	} elsif (@ARGV[0] eq "/oacr" || @ARGV[0] eq "-oacr"){
	    $oacr = 1;
	    shift @ARGV; #eat up the first arg
	}
    }
}

###### Main processing #######

ProcessOptions();

## Clean
Clean();

# infer environment variables
InferHavocDllDir();
InferHavocFeConfig();

# check to see if houdini is used, need args for CL
InferUseHoudini(@ARGV);

## ESPFE 
RunEspFe();

## generate the Blob
GenerateBlob();

## Translator
RunTranslator();

print("Done.\n");
